package com.NeuglsWorkStudio.Utility
{
	import com.NeuglsWorkStudio.Colors.HSL;
	import com.NeuglsWorkStudio.Colors.RGB;
	
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.BlendMode;
	import flash.display.DisplayObject;
	import flash.display.Loader;
	import flash.display.Sprite;
	import flash.geom.Matrix;
	import flash.geom.Rectangle;

	/**
	 * This provider some common used functions
	 * @author Neugls
	 * **/
	public class Utility
	{
		public function Utility()
		{
		}
		
		/**
		 * Process display object position in the container.
		 * it may have four kinds of position.<code>bpFill,bpFit,bpStretch,bpTile,bpCenter</code> which 
		 * has been defined in the <code>Consts</code> package.
		 * @param ContainerWidth The width of the container
		 * @param ContainerHeight The height of the container
		 * @param DO The display object which would be played in the container
		 * @param PositionType Which kind of postion the display object would take
		 *  
		 * **/
		public static function ProcessDisplayObjectPosition(ContainerWidth:Number,ContainerHeight:Number,DO:DisplayObject,PositionType:String="Fill"):void{
			switch(PositionType){
				case nConsts.bpCenter:
					with(DO){
						x=(ContainerWidth-width)/2;
						y=(ContainerHeight-height)/2;
					}
					break;
				case nConsts.bpFill:
					var sr:Number=ContainerWidth/ContainerHeight;
					var ir:Number=DO.width/DO.height;
					if(sr<ir){
						DO.height=ContainerHeight;
						DO.width=DO.height*ir;
						with(DO){
							x=(ContainerWidth-width)/2;
							y=(ContainerHeight-height)/2;
						}
					}else{
						DO.width=ContainerWidth;
						DO.height=DO.width/ir;
						with(DO){
							x=(ContainerWidth-width)/2;
							y=(ContainerHeight-height)/2;
						}
					}
					break;
				case nConsts.bpFit:
					var sr1:Number=ContainerWidth/ContainerHeight;
					var ir1:Number=DO.width/DO.height;
					if(sr1<ir1){
						if(DO.width>ContainerWidth){
							DO.width=ContainerWidth;
							DO.height=DO.width/ir1;
						}
					}else{
						if(DO.height>ContainerHeight){
							DO.height=ContainerHeight;
							DO.width=DO.height*ir1;
						}
					}
					break;
				case nConsts.bpStretch:
					DO.width=ContainerWidth;
					DO.height=ContainerHeight;
					break;
				case nConsts.bpTile:
					//这里不做任何工作。
					break;
			}
		}
		
		
		/**
		 * This function used to create a gradient bitmapdata.
		 * @param W The width of bitmap data
		 * @param H The height of bitmap data
		 * @param BaseColor The base color of the bitmap
		 * @param ButtonNeedHightLight indicate the bitmap should have a hight light line at the button
		 * @param PartHightLight indicate wether the top part of the btimapdata is highted. default is true;
		 * @author Neugls 2011.6.16
		 * */
		public static function CreateGradientBitmapData(W:Number,H:Number,BaseColor:int=0x222222,
			BottomNeedHightLight:Boolean=true,PartHightLight:Boolean=true):BitmapData{
			
			var baseColor:HSL=HSL.RGB2HSL(BaseColor);
			var startColor:int=new HSL(baseColor.Hue,baseColor.Saturation,baseColor.Luminance+0.065).toRGB().Hex;
			var lightColor:int=new HSL(baseColor.Hue,baseColor.Saturation,baseColor.Luminance+0.14).toRGB().Hex;
			var darkColor:int=new HSL(baseColor.Hue,baseColor.Saturation,baseColor.Luminance-0.065).toRGB().Hex;
			var HightLightHeight:Number=1;
			var DarkLightHeight:Number;
			var BlackLightHeight:Number;
			BottomNeedHightLight?DarkLightHeight=1:DarkLightHeight=0;
			BottomNeedHightLight?BlackLightHeight=1:BlackLightHeight=0;
			
			
			var colorLength:int=GetColorLength(BaseColor,startColor);
			var PerColorHeight:Number=(H-HightLightHeight-DarkLightHeight-BlackLightHeight)/colorLength;
			
			var bitmapData:BitmapData=new BitmapData(W,H,true,0);
			var lastY:Number=0;
			bitmapData.fillRect(new Rectangle(0,lastY,W,HightLightHeight),MakeColor(lightColor,0xFF));
			lastY=HightLightHeight;
			for(var i:int=0;i<colorLength;i++){
				var rec:Rectangle=new Rectangle(0,lastY,W,PerColorHeight);
				lastY+=PerColorHeight;
				var color:int=SubColor(startColor,i);
				color=MakeColor(color,0xFF);
				bitmapData.fillRect(rec,color);				
			}
			var rect:Rectangle=new Rectangle(0,lastY,W,H-lastY-DarkLightHeight-BlackLightHeight);
			bitmapData.fillRect(rect,MakeColor(BaseColor,0xFF));	
			if(BottomNeedHightLight){
				rect=new Rectangle(0,H-DarkLightHeight-BlackLightHeight,W,DarkLightHeight);
				bitmapData.fillRect(rect,MakeColor(darkColor,0xFF));
				
				rect=new Rectangle(0,H-BlackLightHeight,W,BlackLightHeight);
				bitmapData.fillRect(rect,MakeColor(0x010101,0xFF));
			}
			
			if(PartHightLight){
				var s:Sprite=new Sprite();
				with(s.graphics){
					beginFill(0xBBBBBB,0.1);
					drawRect(0,0,W,H/2);
					endFill();
				}
				bitmapData.draw(s,null,null,BlendMode.HARDLIGHT,null,true);
				s=null;
			}
			
			return bitmapData;
		}
		
		/**
		 * 这个函数的前提是认为R=G=B
		 * */
		public static function GetColorLength(colorBase:int,ColorTarget:int):int{
			var r:Number = (colorBase>>16) % 256;
			var g:Number = (colorBase>>8) % 256;
			var b:Number = colorBase % 256;
			
			var rr:Number = (ColorTarget>>16) % 256;
			var gg:Number = (ColorTarget>>8) % 256;
			var bb:Number = ColorTarget % 256;
			return Math.max(rr-r,gg-g,bb-b);
		}
		
		public static function SubColor(colorBase:int,colorStep:int):int{
			var r:Number = (colorBase>>16) % 256;
			var g:Number = (colorBase>>8) % 256;
			var b:Number = colorBase % 256;
			
			r-=colorStep;
			g-=colorStep;
			b-=colorStep;
			
			return new RGB(r,g,b).Hex;
		}
		
		/**
		 * 生成ARGB颜色
		 * */
		public static function MakeColor(color:int,Alpha:int):int{
			return color|(Alpha<<24);
		}
		
		
		public static const BtnMouseOver:int=0;
		public static const BtnMouseDown:int=1;
		public static const BtnDisabled:int=2;
		
		/**
		 * Use this function to create a button bitmap, you can use this bitmap data
		 * to make beautiful buttons.
		 * @param W the width of the bitmap
		 * @param H the height of the bitmap
		 * @param BaseColor the color of the bitmap
		 * @param Model which kind of model, it's value maybe BtnMouseOver,BtnMouseDown,BtnDisabled
		 * @author Neugls 2011.6.17
		 * */
		public static function CreateBtnBitmap(W:Number,H:Number,BaseColor:int,Model:int):BitmapData{
			var b:BitmapData;
			switch(Model){
				case BtnMouseOver:
					b= CreateBtnMouseOverBitmap(W,H,BaseColor);
					break;
				case BtnMouseDown:
					b= CreateBtnMouseDownBitmap(W,H,BaseColor);
					break;
				case BtnDisabled:
					b= CreateBtnDisabledBitmap(W,H,BaseColor);
					break;
			}
			return b;
		}
		
		
		public static const glsHorizontal:int=0;
		public static const glsVertical:int=1;
		
		/**
		 * Create a gradient line
		 * @param L the length of the line
		 * @param BaseColor the color of line
		 * @param Sytle indicate whether the line is horizontal or vertical, it's value can be glsHorizontal,glsVertical
		 * */
		public static function CreateGradientLine(L:Number,BaseColor:int,Sytle:int):void{
			
		}
		
		private static function CreateBtnMouseOverBitmap(W:Number,H:Number,BaseColor:int):BitmapData{
			return null;
		}
		private static function CreateBtnMouseDownBitmap(W:Number,H:Number,BaseColor:int):BitmapData{
			return null;
		}
		private static function CreateBtnDisabledBitmap(W:Number,H:Number,BaseColor:int):BitmapData{
			return null;
		}
		
		/**
		 * 将Loader 对象变成bitmapData对象。
		 * @param ALoader Loader对象。
		 * @param W 对象宽度。
		 * @param H 对象高度。
		 * @param IsImage Loader加载的是图片吗？
		 * @param FreeLoader 是否释放Loader对象。
		 * */
		public static function LoaderToBitmap(ALoader:Loader,W:Number,H:Number,FreeLoader:Boolean=true):BitmapData{
			var bitmapData:BitmapData;
			var s:Sprite=new Sprite();
			var FW:Number;
			var FH:Number;
			s.addChild(ALoader);
			
			FW=W;
			FH=H;
			
			bitmapData=new BitmapData(W,H,true);
			var matrix:Matrix=new Matrix();
			matrix.scale(W/s.width,H/s.height);
			bitmapData.draw(s,matrix);
				
			if(FreeLoader){
				s=null;
				ALoader.unload();
				ALoader=null;
			}
			return bitmapData;
			
		}
		
		
		/**
		 * 将DisplayObect转换成Bitmap
		 * @param D 显示对象。
		 * @param W 对象宽度。
		 * @param H 对象高度。
		 * @param FreeDisplayObject 是否释放显示对象。
		 * **/
		public static function DisplayObjectToBitmap(D:DisplayObject,W:Number,H:Number,FreeDisplayObject:Boolean=true):BitmapData{
			var bitmapData:BitmapData;
			var s:Sprite=new Sprite();
			var FW:Number;
			var FH:Number;
			s.addChild(D);
			
			FW=W;
			FH=H;
			
			bitmapData=new BitmapData(W,H,true);
			var matrix:Matrix=new Matrix();
			matrix.scale(W/s.width,H/s.height);
			bitmapData.draw(s,matrix);
			
			if(FreeDisplayObject){
				s=null;
				if( D is Loader){
					(D as Loader).unload();
				}
				D=null;
			}
			return bitmapData;
		}
		
		/**
		 * 缩放BitmapData大小
		 * @param D BitmapData对象。
		 * @param W 对象宽度。
		 * @param H 对象高度。
		 * **/
		public static function ChangeBitmpaDataSize(D:BitmapData,W:Number,H:Number):BitmapData{
			var bitmapData:BitmapData;
			bitmapData=new BitmapData(W,H,true);
			var matrix:Matrix=new Matrix();
			matrix.scale(W/D.width,H/D.height);
			bitmapData.draw(D,matrix);
			
			return bitmapData;
		}
		
		
		
		public static const tdUp:int=0;
		public static const tdDown:int=1;
		public static const tdLeft:int=2;
		public static const tdRight:int=3;
		
		
		/**
		 * 创建一个正三解形。注册点在中心，没有边
		 * @param Direction 正三角形的方向，取值可以是tdUp,tdDown,tdLeft,tdRight.
		 * @param W 三角形的宽度。
		 * */
		public static function CreateTriangle(Direction:int,W:Number,AColor:int):Sprite{
			var result:Sprite=new Sprite();
			var triangleVertialLength:Number=W/2*Math.sqrt(3);
			var CenterToBorder:Number=Math.sqrt(3)*W/6;
			with(result.graphics){
				lineStyle(0,0,0,true);
				beginFill(AColor,1);
				switch(Direction){
					case tdUp:
						moveTo(0,CenterToBorder-triangleVertialLength);
						lineTo(-W/2,CenterToBorder);
						lineTo(W/2,CenterToBorder);
						break;
					case tdDown:
						moveTo(0,-CenterToBorder);
						lineTo(-W/2,-CenterToBorder);
						lineTo(0,triangleVertialLength-CenterToBorder);
						lineTo(W/2,-CenterToBorder);
						
						break;
					case tdLeft:
						moveTo(CenterToBorder,0);
						lineTo(CenterToBorder,W/2);
						lineTo(CenterToBorder-triangleVertialLength,0);
						lineTo(CenterToBorder,-W/2);
						lineTo(CenterToBorder,0);
						break;
					case tdRight:
						moveTo(-CenterToBorder,0);
						lineTo(-CenterToBorder,W/2);
						lineTo(triangleVertialLength-CenterToBorder,0);
						lineTo(-CenterToBorder,-W/2);
						break;
				}
				endFill();
			}
			
			return result;
		}
		
		/**
		 * 处理URL.并判断URL的格式是否正确。需要特别说明的是，如果
		 * 要打开一个网站，而前面没有加上http的话，该函数会给它加上
		 * */
		public static function ValidateURL(URL:String):String{
			var T:String=URL.toLowerCase();
			if(T.indexOf('http://')<0)
				T='http://'+T;
			return T;
		}
	}
}